package UI;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.util.List;

import java_cup.runtime.Symbol;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;

import src.CalcLexer;
import src.CalcParser;
import Exceptions.*;
import command.*;

public class HelloCUP extends JFrame implements ActionListener, KeyListener{

	private JPanel _myPanel;
	private JTextArea _code = new JTextArea();
	private JButton _compile = new JButton("Check Syntax");
	private JButton _run = new JButton("Run");
	private JTable _table = new JTable();
	private JScrollPane _scrollPane;

	private JButton _createT = new JButton("Create");
	private JButton _dropT = new JButton("Drop");
	private JButton _selectT = new JButton("Select");
	private JButton _insertT = new JButton("Insert");
	private JButton _updateT = new JButton("Update");
	private JButton _deleteT = new JButton("Delete");
	private JTextArea _messageText = new JTextArea();
	private JTabbedPane _tabbedPane;
	private JPanel messages = new JPanel();
	public HelloCUP() {
		super();
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setSize(600, 700);
		this.setLayout(null);
		_myPanel = new JPanel();
		_myPanel.setLayout(null);
		_myPanel.setBounds(0, 0, 600, 350);
		_myPanel.setVisible(true);
		
		_code.setBounds(10, 10, 480, 290);
		_code.setLineWrap(true);
		_myPanel.add(_code);
		_code.setVisible(true);
		Font CourierNew = new Font("Courier New", Font.PLAIN, 15);
		_code.setFont(CourierNew);
		_compile.setBounds(200, 300, 90, 30);
		_run.setBounds(300, 300, 90, 30);
		_myPanel.add(_compile);
		_myPanel.add(_run);
		_code.addKeyListener(this);
		

		_createT.setBounds(490, 10, 90, 30);
		_dropT.setBounds(490, 50, 90, 30);
		_selectT.setBounds(490, 90, 90, 30);
		_insertT.setBounds(490, 130, 90, 30);
		_updateT.setBounds(490, 170, 90, 30);
		_deleteT.setBounds(490, 210, 90, 30);

		_createT.addActionListener(this);
		_dropT.addActionListener(this);
		_selectT.addActionListener(this);
		_insertT.addActionListener(this);
		_updateT.addActionListener(this);
		_deleteT.addActionListener(this);
		
		_myPanel.add(_createT);
		_myPanel.add(_dropT);
		_myPanel.add(_selectT);
		_myPanel.add(_insertT);
		_myPanel.add(_updateT);
		_myPanel.add(_deleteT);
		
		_tabbedPane = new JTabbedPane();
		_tabbedPane.setBounds(0, 350, 580, 280);
		_tabbedPane.setVisible(true);
		messages.setLayout(null);
		messages.setBounds(0,0,600,250);
		_messageText.setBounds(0,0,580,250);
		messages.add(_messageText);
		
		
		_tabbedPane.addTab("Messages", messages);
		_myPanel.add(_tabbedPane);
		this.add(_myPanel);
		this.addKeyListener(this);
		this.add(_tabbedPane);
		this.setVisible(true);
		this.add(_tabbedPane);
		
		_compile.addActionListener(this);
		_run.addActionListener(this);
	}

	public static void main(String[] args) throws InterruptedException {

		new HelloCUP();
		Thread.sleep(1000000000);
	}
	public void evalStatements(IStatement i){
		if (i.getClass() == SelectStatement.class) {
			try {
				ResultNode rN = i.eval();
				 Font SansSerif = new Font ("Helvetica", Font.PLAIN, 15);
				String[][] data = rN.getTable();
				String[] header = rN.getHeader();

				_table = new JTable((Object[][]) data,
						(Object[]) header);
				_table.setFont(SansSerif);
				_scrollPane = new JScrollPane(_table);
				_table.setFillsViewportHeight(true);
				_scrollPane.setBounds(10, 330, 565, 200);
				_table.setBounds(0, 0, 565, 200);
				
				_tabbedPane.add(_scrollPane,"Query");
				this.repaint();
			} catch (Exception e) {
				_messageText.setText(_messageText.getText() + "\n" + e.getMessage());
			} 
			
		}
		if (i.getClass() == InsertStatement.class) {
			try {
				ResultNode rN = i.eval();
				_messageText.setText(_messageText.getText() + "\n" + rN.getNrRows()
						+ " rows affected!");
				this.repaint();
			} catch (Exception e) {
				_messageText.setText(_messageText.getText() + "\n" + e.getMessage());
			} 
		}

		if (i.getClass() == UpdateStatement.class) {
			try {
				ResultNode rN = i.eval();
				_messageText.setText(_messageText.getText() + "\n" + rN.getNrRows()
						+ " rows affected!");
				this.repaint();
			} catch (Exception e) {
				_messageText.setText(_messageText.getText() + "\n" + e.getMessage());
			} 
		}

		if (i.getClass() == DeleteStatement.class) {
			try {
				ResultNode rN = i.eval();
				_messageText.setText(_messageText.getText() + "\n" + rN.getNrRows()
						+ " rows affected!");
				this.repaint();
			} catch (Exception e) {
				_messageText.setText(_messageText.getText() + "\n" + e.getMessage());
			} 
		}
		if (i.getClass() == CreateStatement.class) {
			try {
				i.eval();
				_messageText.setText(_messageText.getText() + "\n" + "Table created!");
				
				this.repaint();
			} catch (Exception e) {
				_messageText.setText(_messageText.getText() + "\n" + e.getMessage());
			}
		}
		if (i.getClass() == DropStatement.class) {

			try {
				
				i.eval();
				_messageText.setText(_messageText.getText() + "\n" + "Table dropped!");
				this.repaint();
			} catch (Exception e) {
				_messageText.setText(_messageText.getText() + "\n" + e.getMessage());
			}
	}
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		String template = "";
		Boolean tr = false;
		if (arg0.getSource() == _createT) {
			template = "CREATE TABLE <name>\n (<col1>,<col2>,...) \n"+
			"PRIMARY KEY <col>";
			tr = true;
		}
		if (arg0.getSource() == _dropT) {
			template = "DROP TABLE <name>";
			tr = true;
		}
		if (arg0.getSource() == _selectT) {
			template = "SELECT <fields>|* \nFROM <name> \nWHERE <col> = \"value\" ";
			tr = true;
		}
		if (arg0.getSource() == _insertT) {
			template = "INSERT INTO <name> (<col1>,<col2>,...) \n VALUES (<val1>,<val2>,...)";
			tr = true;
		}
		if (arg0.getSource() == _updateT) {
			template = "UPDATE <name> \n SET <col> = <value> , \n ... \n"+
			"WHERE <col> = \"value\"";
			tr = true;
		}
		if (arg0.getSource() == _deleteT) {
			template = "DELETE FROM <name> \n WHERE <col1> = \"value\"";
			tr = true;
		}
		if(tr == true) {
			_code.setText(template);
		}
		if (arg0.getSource() == _compile) {
			compile();
		}
		if (arg0.getSource() == _run) {
			run();
		}
	}
	private void run() {
		_messageText.setText("");
		_tabbedPane.removeAll();
		_tabbedPane.add(messages,"Results");
		CalcLexer lexer = new CalcLexer(new ByteArrayInputStream(_code
				.getText().getBytes(Charset.defaultCharset())));
		CalcParser parser = new CalcParser(lexer);
		try {
			Symbol t = parser.parse();

			List<IStatement> i = (List<IStatement>) t.value;
			for(IStatement trop : i) {
				this.evalStatements(trop);
			}
			if (_scrollPane != null)
				_myPanel.remove(_scrollPane);

			}
		 catch (Exception e) {
			e.printStackTrace();
			JOptionPane.showMessageDialog(this, "Error!");
		}
	}
	private void compile() {
		CalcLexer lexer = new CalcLexer(new ByteArrayInputStream(_code
				.getText().getBytes(Charset.defaultCharset())));
		CalcParser parser = new CalcParser(lexer);
		try {
			parser.parse();
			JOptionPane.showMessageDialog(this, "Parsed sucessfully!");
		} catch (Exception e) {
			e.printStackTrace();
			JOptionPane.showMessageDialog(this, "Could not parse!");
		}
	}
	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		if(arg0.getKeyCode() == KeyEvent.VK_F7) {
			compile();
		}
		if(arg0.getKeyCode() == KeyEvent.VK_F5) {
			run();
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
	
	}
}
